package lastfm;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;

import randomwalk.Submatrix;
import musictrackrecommendation.DatabaseDataset;
import musictrackrecommendation.Dataset;
import musictrackrecommendation.ExperimentParameters;

public class LastfmUserUserSubmatrix extends Submatrix {
	
	public static final String USER1_ID = "user1_id";
	public static final String USER2_ID = "user2_id";

	public LastfmUserUserSubmatrix() throws ClassNotFoundException, SQLException {
		super();
	}
	
	public LastfmUserUserSubmatrix(int [] rowIds, int[] columnIds, 
    		double[] values, double[] transponedValues) {
		super(rowIds, columnIds, values, transponedValues);
	}

	@Override
	public String getTableName() {
		return LastfmDataset.USER_USER_TABLE_NAME;
	}
	

	@Override
	public String getRowFieldName() {
		return USER1_ID;
	}

	@Override
	public String getColumnFieldName() {
		return USER2_ID;
	}
	
	@Override
	public String getOrderFieldName() {
		return LastfmDataset.ID_ATTRIBUTE;
		//return USER1_ID;
	}

	@Override
	public int getSubmatrixSize() {
		ExperimentParameters parameters = ExperimentParameters.getInstance();		
		Dataset datasetProperties = parameters.getDatasetProperties();
		return datasetProperties.getUserUserCount();
	}

	@Override
	public double[] getSubmatrixValues(int[] friendIds) {
		ExperimentParameters parameters = ExperimentParameters.getInstance();
		int methodCode = parameters.getUserUserValueRetrievalMethod();
		
		switch (methodCode) {
        case ExperimentParameters.GET_AVERAGE_PLAYCOUNT:  
        	return getUserAveragePlaycount(friendIds);       
		case ExperimentParameters.GET_COSINE_SIMILARITY:  
        	return getCosineSimilarity(friendIds.length);
		default: 
        	return null;
		}
	}

	private String getUserTrackTableName() {
		ExperimentParameters parameters = ExperimentParameters.getInstance();
		DatabaseDataset datasetDatabase = parameters.getDatasetDatabase();
		return datasetDatabase.getUserTrackTableName();
	}
	
	
	private double[] getUserAveragePlaycount(int[] friendIds) {
    	double[] averagePlayCounts = new double[friendIds.length];
    	
    	ExperimentParameters parameters = ExperimentParameters.getInstance();
		DatabaseDataset datasetDatabase = parameters.getDatasetDatabase();

        try {
        	Class.forName(datasetDatabase.getJdbcDriverName());

            Connection con =
                    DriverManager.getConnection(
                    		datasetDatabase.getJdbcConnectionUrl(),
                    		datasetDatabase.getDatabaseUser(), 
                    		datasetDatabase.getPassword());

            Statement stmt = con.createStatement();
            String query = "SELECT user_id, avg( playcount ) FROM " + getUserTrackTableName() + " GROUP BY user_id";
            ResultSet rs = stmt.executeQuery(query);

            HashMap<Integer, Double> userAveragePlayCount = new HashMap<Integer, Double>();
            while (rs.next()) {
                 userAveragePlayCount.put(rs.getInt(1), rs.getDouble(2));
            }
            con.close();
            stmt.close();
            
            for(int i = 0; i < friendIds.length; i++) {
                averagePlayCounts[i] = userAveragePlayCount.get(friendIds[i]);
            }

        } 
        catch (ClassNotFoundException e) {
			System.out.println("Cannot register JDBC driver");
			e.getMessage();
		} catch (SQLException e) {
			System.out.println("Cannot retrieve data from database");
			e.getMessage();
		}
        return averagePlayCounts;
    }
    
    private double[] getCosineSimilarity(int length) {
    	double[] similarity = new double[length];
        try {
        	ExperimentParameters parameters = ExperimentParameters.getInstance();
    		DatabaseDataset datasetDatabase = parameters.getDatasetDatabase();
    		
    		Class.forName(datasetDatabase.getJdbcDriverName()); 

	        Connection con =
	                DriverManager.getConnection(
	                		datasetDatabase.getJdbcConnectionUrl(),
	                		datasetDatabase.getDatabaseUser(), 
	                		datasetDatabase.getPassword());

            Statement stmt = con.createStatement();
            String query = "SELECT similarity FROM " + getTableName() + " ORDER BY "+ getOrderFieldName();
            ResultSet rs = stmt.executeQuery(query);

            int i = 0;
            while (rs.next()) {
            	similarity[i] = rs.getDouble(1);
            	i++;
            }
            con.close();
            stmt.close();
        } 
        catch (ClassNotFoundException e) {
			System.out.println("Cannot register JDBC driver");
			e.getMessage();
		} catch (SQLException e) {
			System.out.println("Cannot retrieve data from database");
			e.getMessage();
		}
        return similarity;
    }
}
